package org.aerie.forest.extensions.base.rebar.bootable;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import org.aerie.forest.core.frame.rebar.entity.bootable.ForestBootable;

/**
 * @description UUID池
 *
 * @author quark
 * @organization aerie
 * @date 2020年2月27日 下午5:41:35
 * @version 1.2.0
 */
public final class UuidPool extends ForestBootable {

	/**
	 * @description 存储池
	 * 
	 * @author quark
	 * @date 2020年2月27日 下午5:41:42
	 */
	private static List<String> uuids = new ArrayList<>();

	/**
	 * @description 容量
	 * 
	 * @author quark
	 * @date 2020年2月27日 下午5:41:49
	 */
	private static int capacity = 20;

	/**
	 * @description 随机
	 * 
	 * @author quark
	 * @date 2020年2月27日 下午5:42:05
	 */
	private static Random random = new Random();

	/**
	 * @description 字符库
	 * 
	 * @author quark
	 * @date 2020年2月27日 下午5:42:17
	 */
	private static final String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
			"m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6",
			"7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
			"S", "T", "U", "V", "W", "X", "Y", "Z" };

	/**
	 * @description forest静态内部类单例
	 *
	 * @author quark
	 * @organization aerie
	 * @date 2020-7-9 20:30:37
	 * @version 2.0.1
	 */
	private static final class ForestInstance {

		/**
		 * @description 单例对象
		 * 
		 * @author quark
		 * @date 2020-7-9 21:16:25
		 * @version 2.0.1
		 */
		private static final UuidPool UUID_POOL = new UuidPool();
	}

	/**
	 * Construction
	 * 
	 * @param allowBootFlag 允许启动标识符
	 *
	 * @date 2020年2月27日 下午5:42:37
	 */
	private UuidPool() {
		super(true, "UUID池", new RunnableFunction() {

			/**
			 * @description 负反馈间隔时间【ms】
			 * 
			 * @author quark
			 * @date 2020年2月27日 下午5:43:21
			 */
			private int interval = 10000;

			@Override
			public void action() throws Exception {
				LOGGER.debug("UUID池启动");
				// 如果库存不足补充库存【如果库存清空启动内部自调节】
				if (uuids.size() < capacity / 3) {
					if (uuids.isEmpty()) {
						// 时间间隔缩短10%
						interval = interval / 10 * 9;
						// 库存扩容5
						capacity += 5;
						LOGGER.debug("UUID池扩容");
					}
				} else if (uuids.size() > capacity / 3 * 2) {
					// 逆向调节
					interval *= 1.1;
					capacity -= 1;
				}
				// 补充库存
				supplement();
				Thread.sleep(interval);
			}
		});
		forestFrameName = "UUID池";
		thread = new Thread(bootModule);
		LOGGER.info(LogMsgPool.INIT_COMPLETE, forestFrameName);
	}

	/**
	 * @description 获得UUID池单例
	 * @return UUID池
	 *
	 * @date 2020年2月27日 下午5:45:16
	 */
	static UuidPool getInstance() {
		return ForestInstance.UUID_POOL;
	}

	/**
	 * @description 增补数据
	 *
	 * @date 2020年2月27日 下午5:45:28
	 */
	private static void supplement() {
		while (uuids.size() < capacity) {
			uuids.add(UUID.randomUUID().toString());
		}
		LOGGER.debug("UUID池增补完成");
	}

	/**
	 * @description 获取Uuid,并将其从存储池中移除
	 * @return Uuid的值
	 *
	 * @author quark
	 * @date 2020-8-16 23:14:12
	 * @version 2.0.1
	 */
	public synchronized String getValue() {
		if (uuids.isEmpty()) {
			return UUID.randomUUID().toString();
		}
		String result = uuids.get(0);
		uuids.remove(0);
		return result;
	}

	/**
	 * @description 获得短八位UUID【集群服务不可用】
	 * @return 八位UUID
	 *
	 * @date 2020年2月27日 下午5:46:22
	 */
	public synchronized String getUUIDEightBit() {
		StringBuilder stringBuffer = new StringBuilder();
		for (int i = 0; i < 8; i++) {
			String str = getValue().replace("-", "").substring(i * 4, i * 4 + 4);
			int index = Integer.parseInt(str, 16);
			stringBuffer.append(chars[index % 0x3E]);
		}
		return stringBuffer.toString();
	}

	/**
	 * @description 获得短十二位UUID【集群服务不可用】
	 * @return 十二位UUID
	 *
	 * @date 2020年2月27日 下午5:47:05
	 */
	public synchronized String getUUIDTwelveBit() {
		StringBuilder stringBuffer = new StringBuilder("-" + getUUIDEightBit());
		stringBuffer.insert(8, random.nextInt(9)).insert(5, "-").insert(5, random.nextInt(9));
		return stringBuffer.toString();
	}

	/**
	 * @description 处理异常
	 * @param exception 需要处理的异常
	 *
	 * @date 2020年2月27日 下午5:47:15
	 */
	@Override
	protected void disposeException(Exception exception) {
//		ExceptionProcessor.INSTANCE.recordException("UUID池", exception, new ExceptionDisposeFunction() {
//
//			@Override
//			public void action() {
//				// 设置中断标识
//				Thread.currentThread().interrupt();
//			}
//		});
	}

	/**
	 * @description 启动前动作
	 *
	 * @date 2020年2月27日 下午5:47:28
	 */
	@Override
	protected void beforeRun() {
		// Do Nothing
	}

	/**
	 * @description 启动后动作
	 *
	 * @date 2020年2月27日 下午5:48:20
	 */
	@Override
	protected void afterRun() {
		// Do Nothing
	}

}
